/*
 */
package org.vectrics.config;

import java.io.File;
import java.net.URL;
import java.util.Collection;
import java.util.Date;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.vectrics.SystemException;
import org.vectrics.common.util.ConfigurationReader;
import org.vectrics.common.util.FileUtil;
import org.vectrics.domain.Domain;
import org.vectrics.provider.CoreServiceLocator;
import org.vectrics.user.Person;

/**
 * @author mmoore
 */
public abstract class ApplicationConfiguration extends ConfigurationReader {

    // private static ApplicationConfiguration instance = null;
    public static String BEAN_ID = "configuration";

    public static final String SYSTEM_CONSTANT_KEY_SINGLE_DATA_OWNER = "domain.single";

    private String hibernateDialect = null;

    private String jdbcDriver;

    private String serverIp = null;

    private boolean testMode = false;

    protected ApplicationConfiguration() {
        super();
    }

    public abstract Collection getAllMenus();

    public boolean getAllowPasswordEmail(Domain domain) {
        return CoreServiceLocator.getSystemService().findSystemConstant(domain, "security.pwd.email.candidate")
                .getBooleanValue().booleanValue();
    }

    public boolean getAllowTasks() {
        return CoreServiceLocator.getSystemService().findGlobalSystemConstant("module.task").getBooleanValue()
                .booleanValue();
    }

    /**
     * @deprecated This is not portable, use getApplicationDataDirectory2.
     */
    @Deprecated
    public String getApplicationDataDirectory() {
        String directory = this.getDataDirectory() + "/application/" + this.getApplicationDirectoryName();
        return (directory);
    }

    public File getApplicationDataDirectory2() {
        File directory = new File(this.getDataDirectory2(), "/application/" + this.getApplicationDirectoryName());
        return (directory);
    }

    public abstract String getApplicationDirectoryName();

    public Person getBatchPerson() {
        Long batchPersonId = CoreServiceLocator.getSystemService().getLongSystemConstant("person.batch.person.id",
                this.getSystemDomain());
        Person batchPerson = CoreServiceLocator.getPersonService().findPersonById(batchPersonId);
        return (batchPerson);
    }

    public String getCacheDirectory() {
        String value = this.getData() + "/cache/" + this.getApplicationDirectoryName();
        FileUtil.createDirectoryIfNotExist(value);
        return (value);
    }

    /**
     * @deprecated This is not portable, use getDataDirectory2.
     */
    @Deprecated
    public String getDataDirectory() {
        String value = CoreServiceLocator.getSystemService().findGlobalSystemConstant("data.host").getValue()
                + this.getData();
        return (value);
    }

    public File getDataDirectory2() {
        URL dataDirURL = this.getClass().getResource("/");
        File value = FileUtils.toFile(dataDirURL);
        value = value.getParentFile();
        value = value.getParentFile();
        value = new File(value, "data/hexacta");
        return (value);
    }

    /**
     * Does application display debug information on HTML/GUI forms.
     * 
     * @return
     */
    public boolean getDebugDisplay() {
        return CoreServiceLocator.getSystemService().findGlobalSystemConstant("debug.display").getBooleanValue()
                .booleanValue();
    }

    public String getDefaultAreaCode(Domain domain) {
        String areaCode = CoreServiceLocator.getSystemService().findSystemConstant(domain, "company.area.code")
                .getValue();
        return (areaCode);
    }

    public Locale getDefaultLocale() {
        // This must
        return (Locale.getDefault());
    }

    public String getDynaImageCacheDirectory() {
        String value = this.getCacheDirectory() + "/dynaimages";
        FileUtil.createDirectoryIfNotExist(value);
        return (value);
    }

    public String getDynamicContentPath(Domain domain) {
        return this.getApplicationDataDirectory() + "/dynamic-content/domain-default";
    }

    public boolean getEmailMustBeUnique(Domain domain) {
        boolean emailUnique = false;
        if (this.getAllowPasswordEmail(domain)) {
            emailUnique = true;
        } else {
            emailUnique = CoreServiceLocator.getSystemService().findSystemConstant(domain, "email.primary.unique")
                    .getBooleanValue().booleanValue();
        }
        return (emailUnique);
    }

    public String getEmailStagingBaseDirectory() {
        String directory = this.getData() + "/application/" + this.getApplicationDirectoryName();
        FileUtil.createDirectoryIfNotExist(directory);
        return (directory + "/email-staging");
    }

    public String getEmailStagingDirectory(Person owner, Date date) {
        String directory = this.getEmailStagingBaseDirectory();
        return (directory + "/" + owner.getId() + "-" + date.getTime());
    }

    public String getEmailTemplateDirectory() {
        String applicationDirectory = this.getData() + "/application/" + this.getApplicationDirectoryName();
        return (applicationDirectory + "/email-templates");
    }

    public long getEventRetries(Domain domain) {
        return CoreServiceLocator.getSystemService().findSystemConstant(domain, "event.error.retry").getLongValue()
                .longValue();
    }

    public abstract MailConfiguration getFromMailConfiguration(Domain domain);

    /**
     * @return Returns the hibernateDialect.
     */
    public String getHibernateDialect() {
        return this.hibernateDialect;
    }

    public abstract Map<String, String> getHibernateProperties();

    /**
     * @deprecated Use getHtmlStyleDirectory2 instead.
     */
    @Deprecated
    public String getHtmlStyleDirectory() {
        String directory = this.getApplicationDataDirectory() + "/html-style";
        return directory;
    }

    public File getHtmlStyleDirectory2() {
        File directory = new File(this.getApplicationDataDirectory2(), "html-style");
        return directory;
    }

    public boolean getJavaScriptDebug() {
        return CoreServiceLocator.getSystemService().findGlobalSystemConstant("debug.javascript").getBooleanValue()
                .booleanValue();
    }

    /**
     * @return Returns the jdbcDriver.
     */
    public String getJdbcDriver() {
        return this.jdbcDriver;
    }

    public File getMenuConfigDirectory(Domain domain) {
        File directory = new File(this.getApplicationDataDirectory2(), "/menus/domain-default");
        return (directory);
    }

    public boolean getPasswordEmailedAfterQuestion(Domain domain) {
        return CoreServiceLocator.getSystemService().findSystemConstant(domain, "security.pwd.email.rqr.quest")
                .getBooleanValue().booleanValue();
    }

    public String getPasswordEncryptKey() {
        return CoreServiceLocator.getSystemService().findGlobalSystemConstant("password.encrypt.key").getValue();
    }

    public String getPhoneNumberRegularExpression(Domain domain) {
        String regExp = CoreServiceLocator.getSystemService().findSystemConstant(domain, "phone.number.reqexp")
                .getValue();
        return (regExp);
    }

    public boolean getRequireEmailForPersonEdit(Domain domain) {
        boolean result = CoreServiceLocator.getSystemService().getBooleanSystemConstant(
                "person.email.required.for.admin", domain).booleanValue();
        return (result);

    }

    public String getServerIp() {
        return this.serverIp;
    }

    public boolean getSimulateEmailing() {
        return CoreServiceLocator.getSystemService().findGlobalSystemConstant("debug.simulate.email").getBooleanValue()
                .booleanValue();
    }

    public boolean getSingleDomain(Domain domain) {
        return CoreServiceLocator.getSystemService().findSystemConstant(domain, SYSTEM_CONSTANT_KEY_SINGLE_DATA_OWNER)
                .getBooleanValue().booleanValue();
    }

    public Domain getSystemDomain() {
        return (CoreServiceLocator.getSystemService().findDomain(this.getSystemDomainId()));
    }

    public Long getSystemDomainId() {
        Long id = CoreServiceLocator.getSystemService().getLongSystemConstantGlobal("system.domain.id");
        return (id);
    }

    public String getSystemEmailFromAddress(Domain domain) {
        String value = CoreServiceLocator.getSystemService().findSystemConstant(domain, "mail.from.address").getValue();
        return (value);
    }

    public String getSystemEmailFromName(Domain domain) {
        String value = CoreServiceLocator.getSystemService().findSystemConstant(domain, "mail.from.name").getValue();
        return (value);
    }

    public Person getSystemPerson() {
        Domain systemDomain = CoreServiceLocator.getSystemService().findDomain(new Long(1));
        Long systemPersonId = CoreServiceLocator.getSystemService().getLongSystemConstant("person.system.person.id",
                systemDomain);
        Person systemPerson = CoreServiceLocator.getPersonService().findPersonById(systemPersonId);
        return (systemPerson);
    }

    public abstract String getTestDatabaseUrl();

    /**
     * @return Returns the testMode.
     */
    public boolean getTestMode() {
        return this.testMode;
    }

    public Person getTestPerson() {
        Long testPersonId = CoreServiceLocator.getSystemService().getLongSystemConstant("person.test.person.id",
                this.getSystemDomain());
        Person testPerson = CoreServiceLocator.getPersonService().findPersonById(testPersonId);
        return (testPerson);
    }

    abstract public String getWorkflowDataSourceJndi();

    /**
     * @param hibernateDialect
     *            The hibernateDialect to set.
     */
    public void setHibernateDialect(String hibernateDialect) {
        this.hibernateDialect = hibernateDialect;
    }

    /**
     * @param jdbcDriver
     *            The jdbcDriver to set.
     */
    public void setJdbcDriver(String jdbcDriver) {
        if (jdbcDriver.startsWith("@@")) {
            throw new SystemException("Configuration file still has tokens that were not replaced by build: "
                    + jdbcDriver);
        }
        this.jdbcDriver = jdbcDriver;
    }

    public void setServerIp(String serverIp) {
        this.serverIp = serverIp;
    }

    /**
     * @param testMode
     *            The testMode to set.
     */
    public void setTestMode(boolean testMode) {
        this.testMode = testMode;
    }

    protected String getData() {
        String value = CoreServiceLocator.getSystemService().findGlobalSystemConstant("data.directory").getValue();
        return (value);
    }

}
